//============================================================
//	COPYRIGHT(C) Innobeam
//	ALL RIGHTS RESERVED
//============================================================
//	Filename	: HHCLCD.v
//	Created On	: 2019-11-02 11:49:49
//	Author		: haoyu.xiao
//	Description	: 
//	Include		: 
//	Modification: 
//============================================================
`timescale	1ns/100ps
`include	"../rtl/def_command.v"

module	HHCPrototype(
	clk_in,
	nReset,
	
	oILI_rst,
	//Key input
	iMoveStop,
	iTouchguardoverride,
	iODILight,
	iFieldDefiningLight,
	iLaserLight,
	iTreatmentRoomLight,
	iMLC,
	iGamma,
	iToCenter,
	iPageRight,
	iPageLeft,
	iLongitudinalBrake,
	iLateralBrake,
	iMoveEn,
	//LED output
	oTouchguardoverrideLed,
	oXLed,
	oX1Led,
	oX2Led,
	oYLed,
	oY1Led,
	oY2Led,
	oGanLed,
	oCollLed,
	oSwingLed,
	oLATLed,
	oLNGLed,
	oVRTLed,
	oLateralBrakeLed,
	oLongitudinalBrakeLed,
	oPageRightLed,
	oPageLeftLed,
	oToCenterLed,
	oGammaLed,
	oMLCLed,
	oTreatmentRoomLightLed,
	oLaserLightLed,
	oFieldDefiningLightLed,
	oODILightLed,
	oLogoLightLed,
	oMoveStopLed,	
	//ILI9341
	oILI_SCLK,//GPIO 6
	iILI_SO,//GPIO 1
	oILI_SI,//GPIO 8
	oILI_CS_n,
	oILI_DCChoice,
	CTRL,
	//CAN-SPI
	i_miso,
	o_sck,
	o_mosi,                
	o_ssn,
	i_mpc_intr_n,
	o2515Reset
	);
	
	input 			clk_in;
	input 			nReset;
	output			oILI_rst;
	//ILI9341
	output			oILI_SCLK;
	input			iILI_SO;
	output			oILI_SI;
	output			oILI_CS_n;
	output			oILI_DCChoice;
	output			CTRL;
	//Key input		14 
	input				iMoveStop;
	input				iTouchguardoverride;
	input				iODILight;
	input				iFieldDefiningLight;
	input				iLaserLight;
	input				iTreatmentRoomLight;
	input				iMLC;
	input				iGamma;
	input				iToCenter;
	input				iPageRight;
	input				iPageLeft;
	input				iLongitudinalBrake;
	input				iLateralBrake;
	input				iMoveEn;	
	//LED output		25
	output				oTouchguardoverrideLed;
	output				oXLed;
	output				oX1Led;
	output				oX2Led;
	output				oYLed;
	output				oY1Led;
	output				oY2Led;
	output				oGanLed;
	output				oCollLed;
	output				oSwingLed;
	output				oLATLed;
	output				oLNGLed;
	output				oVRTLed;
	output				oLateralBrakeLed;
	output				oLongitudinalBrakeLed;
	output				oPageRightLed;
	output				oPageLeftLed;
	output				oToCenterLed;
	output				oGammaLed;
	output				oMLCLed;
	output				oTreatmentRoomLightLed;
	output				oLaserLightLed;
	output				oFieldDefiningLightLed;
	output				oODILightLed;
	output				oLogoLightLed;
	output				oMoveStopLed;
	//CAN
input   i_miso;     
input i_mpc_intr_n;                                                                                                                                                                                                                                                       
output  o_sck  ;                  
output  o_mosi ;                 
output  o_ssn  ;
output o2515Reset;
	
//========================================================================
//		parameters
//========================================================================	
parameter 		DATA_W = 16;//
//states define for FSM	
parameter     	LCD_RESET			= 4'b0000;
parameter     	LCD_INIT 			= 4'b0001;
parameter     	LCD_WAIT 			= 4'b0010;
parameter     	LCD_DISPLAYON		= 4'b0100;
parameter     	LCD_UPDATA 			= 4'b1000;
parameter       LCD_DISPLAYOFF		= 4'b1001;

parameter   	VERSION = 16'd20303;  //版本信息20203代表V2.2.3
parameter   	YEAR 	= 7'd24;  //年
parameter   	MONTH 	= 4'd7;  //月
parameter   	DAY 	= 5'd5;  //日
//========================================================================
//		signal
//========================================================================
	reg				rILI_rst_buf;
	reg		[31:0]	rvByteCnt;
	wire			ILI_rst_negedge;
	wire			ILI_rst_posedge;

	wire			wTx_done;
	wire			wTx_done16;
	wire			wILI_SCLK8;
	wire			wILI_SCLK16;
	wire			wCS_n;
	wire			wCS_n16;
	wire			wILI_SI8;
	wire			wILI_SI16;
//
	wire			wLCD_RST;
	wire			wLCD_DC;
	wire			wLCD_CTRL;
	wire	[7:0]	wvLCD_SPI_TxData;
	wire			wLCD_SPI_Done;
	wire			wLCD_SPI_Start;
	wire			wLCDInitDone;
	wire			wLCDUpdateDone;
	wire			wLCDDisPlayOnDone;
	wire			wLCDDisPlayOffDone;
//	
	wire	[1:0]		ivAddrSel_lan;
	wire	[15:0]		ivAddr_lan;
	wire	[31:0]		ivData_lan;
	wire	[31:0]		ovData_lan;
	wire	[9:0]		ivNum_pram_lan;
	wire		 		nRst;
	wire 				iclk;
	wire 				iclk10;
	wire 				iclk50;
	wire				locked;
	//ADC module
	wire				wADCStart;
	wire	[1:0]		wvCmdCh;
	wire 				wRepValid;
	wire	[2:0]		wvRailCh;
	wire	[11:0]		wvRepData;
	
	wire	[15:0]		wvKey;
	wire	[7:0]		LEDR;
	
	

	reg				rComm_stateTrOut;//通讯状态指示
	
//变量定义
wire		[15:0]		wvHHC_Gantry;
wire		[15:0]		wvHHC_Collimator;		
wire		[15:0]		wvHHC_Swing;		
wire		[15:0]		wvHHC_MLCX1;		
wire		[15:0]		wvHHC_MLCX2;		
wire		[15:0]		wvHHC_JawY1;		
wire		[15:0]		wvHHC_JawY2;	
wire		[15:0]		wvHHC_CouchVRT;
wire		[15:0]		wvHHC_CouchLAT;	
wire		[15:0]		wvHHC_CouchLNG;
wire		[15:0]		wvHHC_CouchLED1;
wire		[15:0]		wvHHC_CouchLED2;
wire		[15:0]		wvHHC_DisplayState;
wire		[15:0]		wvHHC_CouchLNGPLAN;
wire		[15:0]		wvHHC_MLCX;	
wire		[15:0]		wvHHC_MLCY;	
wire  		[15:0]   	wvVersion;
//wheel data
wire		[11:0]		wvwheel1;
wire		[11:0]		wvwheel2;
wire		[11:0]		wvwheel3;
//==============================================================
//mapping end
//==============================================================
reset_delay reset_delay_inst(
			.clk(clk_in),//CLK25
			.ready_in(nReset),
			.ready_out(nRst)
			);


my_pll1 my_pll1_inst(
			.inclk0(clk_in),   //  refclk.clk
			.areset(~nRst),//  reset.reset
			.c0(iclk), // outclk0.clk
			.c2(iclk10),
			.locked(locked)    // locked.export
			);	

//==============================================================
//IO-Link
//==============================================================	
assign wvKey[13:0]={	
					~iMoveStop,	
					~iTouchguardoverride,						
					~iODILight,	
					~iFieldDefiningLight,	
					~iLaserLight,	
					~iTreatmentRoomLight,	
					~iMLC,	
					~iGamma,	
					~iToCenter,	
					~iPageRight,	
					~iPageLeft,	
					~iLongitudinalBrake,
					~iLateralBrake,
					~iMoveEn
					};
assign wvKey[15:14]=2'h0;
assign	oXLed = rComm_stateTrOut ? wvHHC_CouchLED2[8]:1'b0;
assign	oX1Led = rComm_stateTrOut ? wvHHC_CouchLED2[7]:1'b0;
assign	oX2Led = rComm_stateTrOut ? wvHHC_CouchLED2[6]:1'b0;
assign	oYLed = rComm_stateTrOut ? wvHHC_CouchLED2[5]:1'b0;
assign	oY1Led = rComm_stateTrOut ? wvHHC_CouchLED2[4]:1'b0;
assign	oY2Led = rComm_stateTrOut ? wvHHC_CouchLED2[3]:1'b0;
assign	oGanLed = rComm_stateTrOut ? wvHHC_CouchLED2[2]:1'b0;
assign	oCollLed = rComm_stateTrOut ? wvHHC_CouchLED2[1]:1'b0;
assign	oSwingLed = rComm_stateTrOut ? wvHHC_CouchLED2[12]:1'b0;
assign	oLATLed = rComm_stateTrOut ? wvHHC_CouchLED2[11]:1'b0;
assign	oLNGLed = rComm_stateTrOut ? wvHHC_CouchLED2[10]:1'b0;
assign	oVRTLed = rComm_stateTrOut ? wvHHC_CouchLED2[9]:1'b0;
assign	oLateralBrakeLed = rComm_stateTrOut ? wvHHC_CouchLED1[7]	:1'b0;
assign	oLongitudinalBrakeLed = rComm_stateTrOut ? wvHHC_CouchLED1[6]	:1'b0;
assign	oPageRightLed = rComm_stateTrOut ? wvHHC_CouchLED1[4]	:1'b0;
assign	oPageLeftLed = rComm_stateTrOut ? wvHHC_CouchLED1[5]	:1'b0;
assign	oToCenterLed =  rComm_stateTrOut ? wvHHC_CouchLED1[3]	:1'b0;
assign	oGammaLed = rComm_stateTrOut ? wvHHC_CouchLED1[2]	:1'b0;
assign	oMLCLed = rComm_stateTrOut ? wvHHC_CouchLED1[1]	:1'b0;
assign	oTreatmentRoomLightLed = rComm_stateTrOut ? wvHHC_CouchLED1[0]	:1'b0;
assign	oLaserLightLed = rComm_stateTrOut ? wvHHC_CouchLED2[15]	:1'b0;
assign	oFieldDefiningLightLed =  rComm_stateTrOut ? wvHHC_CouchLED2[14]	:1'b0;
assign	oODILightLed = rComm_stateTrOut ? wvHHC_CouchLED2[13]:1'b0;
assign	oTouchguardoverrideLed = rComm_stateTrOut ? wvHHC_CouchLED2[0]:1'b0;
assign	oLogoLightLed = 1'b1;
assign	oMoveStopLed =  wvKey[13];
assign wvVersion[15:0] = VERSION;
//通讯正常信号生成
always@(posedge iclk or negedge nRst)begin
	if(!nRst)
		rComm_stateTrOut<=1'b0;
    else
		rComm_stateTrOut<=1'b1;
end
//==============================================================
//CAN通讯
//==============================================================
wire        [63:0]      wvCanData_send;
wire        [63:0]      wvCanData_receive;
Can_BUS u_Can_BUS(
	.iClk         (iclk         ),
	.iRst_n       (nRst       ),
	.i_mpc_intr_n (i_mpc_intr_n ),
	.i_can_data   (wvCanData_send ),
	.i_miso       (i_miso       ),
	.o_can_data   (wvCanData_receive   ),
	.o_sck        (o_sck        ),
	.o_mosi       (o_mosi       ),
	.o_ssn        (o_ssn        ),
	.iM_S_slect   (1'b0   ),
	.o2515Reset(o2515Reset)
);

CAN_send u_CAN_send(
	.iClk           (iclk           ),
	.iRst_n         (nRst         ),
	.ivHHC_Key      (wvKey      ),
	.ivHHC_Wheel1   (wvwheel1   ),
	.ivHHC_Wheel2   (wvwheel2   ),
	.ivHHC_Wheel3   (wvwheel3   ),
	.ivHHC_VERSION  (wvVersion  ),
	.ovCanData_send (wvCanData_send )
); 

Can_receive u_Can_receive(
	.iClk               (iclk               ),
	.iRst_n             (nRst             ),
	.iCanData_Receive   (wvCanData_receive   ),
	.ovHHC_Gantry       (wvHHC_Gantry       ),
	.ovHHC_Collimator   (wvHHC_Collimator   ),
	.ovHHC_Swing        (wvHHC_Swing        ),
	.ovHHC_MLCX1        (wvHHC_MLCX1        ),
	.ovHHC_MLCX2        (wvHHC_MLCX2        ),
	.ovHHC_JawY1        (wvHHC_JawY1        ),
	.ovHHC_JawY2        (wvHHC_JawY2        ),
	.ovHHC_CouchVRT     (wvHHC_CouchVRT     ),
	.ovHHC_CouchLAT     (wvHHC_CouchLAT     ),
	.ovHHC_CouchLNG     (wvHHC_CouchLNG     ),
	.ovHHC_CouchLED1    (wvHHC_CouchLED1    ),
	.ovHHC_CouchLED2    (wvHHC_CouchLED2    ),
	.ovHHC_DisplayState (wvHHC_DisplayState ),
	.ovHHC_CouchLNGPLAN (wvHHC_CouchLNGPLAN ),
	.ovHHC_MLCX         (wvHHC_MLCX         ),
	.ovHHC_MLCY         (wvHHC_MLCY         )
);
//==============================================================
//波轮
//==============================================================
wheel_monitor wheel_monitor_inst	(
	.iRst_n(nRst),
	.iClk(iclk),
    //to on chip adc
	.oCmdValid(wADCStart), // ctrl sampling frequency
	.ovCmdCh(wvCmdCh), // cmd channal
	//from on chip adc
	.iRailData_en(wRepValid),
	.ivRailCh(wvRailCh),
	.ivRailData(wvRepData),
	//output wheel data value
	.ovwheel1(wvwheel1),
	.ovwheel2(wvwheel2),
	.ovwheel3(wvwheel3)
	);

adc1 adc1_inst (
	.clock_clk              (iclk),              	// clock.clk
	.reset_sink_reset_n     (nRst),     			// reset_sink.reset_n
	.adc_pll_clock_clk      (iclk10),      			// adc_pll_clock.clk
	.adc_pll_locked_export  (locked),  				// adc_pll_locked.export
	.command_valid          (wADCStart),          	// command.valid
	.command_channel        ({4'h0,wvCmdCh}),       // channel
	.command_startofpacket  (1'b1),  				// startofpacket
	.command_endofpacket    (1'b1),    				// endofpacket
	.command_ready          (),          			// ready
	.response_valid         (wRepValid),         	// response.valid
	.response_channel       ({3'h0,wvRailCh}),      // channel
	.response_data          (wvRepData),          	// data
	.response_startofpacket (), 					// startofpacket
	.response_endofpacket   ()    					// endofpacket
	);
//==============================================================
//LCD通讯
//==============================================================
	assign		oILI_rst = wLCD_RST;
	assign 		oILI_DCChoice = wLCD_DC;
	assign		oILI_SI = wILI_SI8;
	assign		oILI_SCLK = wILI_SCLK8;
	assign		oILI_CS_n = wCS_n;//rCS;
	assign 		CTRL = wLCD_CTRL;//wLCD_CTRL;
	
SPIMasterEPD SPIMasterLCD_inst(
	.iClk(iclk),
	.iRst_n(nRst),
	
	.ivData(wvLCD_SPI_TxData),
	.iStart(wLCD_SPI_Start),
	.ovRxData(),
	.oDone(wLCD_SPI_Done),
	
	.oSCLK(wILI_SCLK8),
	.oSI(wILI_SI8),
	.iSO(iILI_SO),
	.oCS_n(wCS_n)
	);
	
	
LCD_Ctrl	LCD_Ctrl_inst(
	.iClk				(iclk),
	.iRst_n				(nRst),
	
	.OLCD_RST			(wLCD_RST),		
	.oLCD_DC			(wLCD_DC),		
	.oLCD_CTRL			(wLCD_CTRL),		
	.ovLCD_SPI_TxData	(wvLCD_SPI_TxData),
	.oLCD_SPI_Start		(wLCD_SPI_Start),	

	.ivLCD_SPI_RxData	(),
	.iLCD_SPI_Done		(wLCD_SPI_Done),
	
	.iComm_stateTrOut	(rComm_stateTrOut),
	.ivDisplay_state	(wvHHC_DisplayState[4:0]),//
	//.ivDisplay_state	(5'd1),//
	.ivGantry			(wvHHC_Gantry),	
	.ivCollimator		(wvHHC_Collimator),	
	.ivSwing			(wvHHC_Swing),	//
	.ivMLCX				(wvHHC_MLCX),
	.ivMLCX1			(wvHHC_MLCX1),	
	.ivMLCX2			(wvHHC_MLCX2),
	.ivJAWY				(wvHHC_MLCY),
	.ivJAWY1			(wvHHC_JawY1),	
	.ivJAWY2			(wvHHC_JawY2),		
	.ivCouch_VRT		(wvHHC_CouchVRT),	
	.ivCouch_LAT		(wvHHC_CouchLAT),	
	.ivCouch_LNG		(wvHHC_CouchLNG),	
	.ivCouch_LNG_PLAN 	(wvHHC_CouchLNGPLAN),	
	
	.iLCDInit			(rLCDInit),
	.iLCDUpdate			(rLCDUpdate),
	.iLCDDisplayOn		(rLCDDisplayOn),
	.iLCDDisplayOff		(rLCDDisplayOff),
	.oLCDUpdateDone		(wLCDUpdateDone),
	.oLCDInitDone		(wLCDInitDone),
	.oLCDDisPlayOnDone	(wLCDDisPlayOnDone),
	.oLCDDisPlayOffDone	(wLCDDisPlayOffDone)
	);


//======Main FSM==============================
reg	[3:0]		rvHHCState;
reg	[31:0]		rvTimerCnt;
reg [3:0]		rvDisplayState;
reg				rLCDInit;		
reg				rLCDUpdate;	
reg				rLCDDisplayOn;
reg				rLCDDisplayOff;

	always@(posedge iclk or negedge nRst)begin
		if(!nRst)begin
			rvHHCState 		<= LCD_RESET;
			rvDisplayState  <= 4'b0000;
			rvTimerCnt 		<= 32'd0;
			rLCDInit		<= 1'b0;
			rLCDUpdate		<= 1'b0;
			rLCDDisplayOn	<= 1'b0;
			rLCDDisplayOff	<= 1'b0;
			end
		else begin
			case(rvHHCState)
			LCD_RESET:begin
			//	if ((rvDisplayState != wvHHC_DisplayState[15:12]) && rComm_stateTrOut && wLCD_RST)begin
				if (wLCD_RST && (rvTimerCnt >= 32'd2_500_000))begin
					rvHHCState		<= LCD_INIT;
					rvDisplayState	<= wvHHC_DisplayState[15:12];
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b1;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;
					end
				else begin
					rvHHCState 		<= LCD_RESET;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= rvTimerCnt + 32'd1;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;
					end
				end
				
			LCD_INIT:begin
				if (wLCDInitDone) begin
					rvHHCState 		<= LCD_WAIT;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;	
					end
				else begin
					rvHHCState 		<= LCD_INIT;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;				
					end
				end 	
				
			LCD_WAIT:begin
			//	if (rvDisplayState != wvHHC_DisplayState[15:12] && wvHHC_DisplayState[11:0] != 12'h00D) begin
				if ((rvDisplayState != wvHHC_DisplayState[15:12] && wvHHC_DisplayState[11:0] != 12'h00D && rComm_stateTrOut) || (rvTimerCnt >= 32'd2_500_000)) begin
					rvHHCState 		<= LCD_UPDATA;
					rvDisplayState	<= wvHHC_DisplayState[15:12];
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b1;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;	
					end
				else if(rvDisplayState != wvHHC_DisplayState[15:12] && wvHHC_DisplayState[11:0] == 12'h00D && rComm_stateTrOut) begin//
					rvHHCState 		<= LCD_DISPLAYOFF;
					rvDisplayState	<= wvHHC_DisplayState[15:12];
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b1;
					end
				else if(wvHHC_DisplayState[11:0] == 12'h00D)
				begin
					rvHHCState 		<= LCD_WAIT;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;	
				end
				else begin
					rvHHCState 		<= LCD_WAIT;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= rvTimerCnt+32'd1;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;	
					end
				end		

				
			LCD_UPDATA:begin
				if (wLCDUpdateDone) begin
					rvHHCState 		<= LCD_WAIT;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;	
					end
				else begin
					rvHHCState 		<= LCD_UPDATA;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;	
					end
				end 		
				
	
				
			LCD_DISPLAYOFF:begin
				if (wLCDDisPlayOffDone) begin
					rvHHCState 		<= LCD_WAIT;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b1;
					end
				else begin
					rvHHCState 		<= LCD_DISPLAYOFF;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b1;
					end
				end
			default: begin
					rvHHCState 		<= LCD_WAIT;
					rvDisplayState	<= rvDisplayState;
					rvTimerCnt 		<= 32'd0;
					rLCDInit		<= 1'b0;
					rLCDUpdate		<= 1'b0;
					rLCDDisplayOn	<= 1'b0;
					rLCDDisplayOff	<= 1'b0;
				end
			endcase	
		end
	end

endmodule
	 